<script setup lang="ts">
import type { Fetcher } from './index'
import { onMounted, ref, watch } from 'vue'
import LoadingContainer from '../LoadingContainer.vue'
import message from '../message'
import PageController from './PageController.vue'

interface Props {
  fetcher: Fetcher
  defaultPageSize?: number
}

const props = withDefaults(defineProps<Props>(), {
  defaultPageSize: 10,
})

// 定义一个forceRefresh模型值，当父组件更新此值时触发刷新
const forceRefresh = defineModel('forceRefresh', { default: 0 })

const loading = ref(true)
const initialized = ref(false)
const page = ref(1)
const total = ref(0)
const pageSize = ref(props.defaultPageSize)

async function fetchData() {
  loading.value = true
  try {
    const result = await props.fetcher(page.value, pageSize.value)
    total.value = result.total
    page.value = result.page
    pageSize.value = result.pageSize
    initialized.value = true
  }
  catch (err) {
    message.error(err instanceof Error ? err.message : '获取列表数据失败！')
  }
  finally {
    loading.value = false
  }
}

async function handlePageChange(newPage: number) {
  page.value = newPage
  await fetchData()
}

// 强制刷新数据，重置到第一页
async function forceFetch() {
  page.value = 1
  await fetchData()
}

// 监听forceRefresh的变化，当值变化时触发刷新
watch(forceRefresh, () => {
  forceFetch()
})

// 暴露方法给父组件使用
defineExpose({
  forceFetch,
})

onMounted(() => {
  fetchData()
})
</script>

<template>
  <LoadingContainer :loading="loading">
    <div class="header">
      <slot name="header" />
    </div>
    <template v-if="initialized">
      <div class="card-area">
        <slot />
        <div v-if="total > 0" class="page-status">
          显示第{{ (page - 1) * pageSize + 1 }}至{{ Math.min(page * pageSize, total) }}条，共{{ total }}条记录
        </div>
        <div v-else class="no-page-data">
          暂无数据
        </div>
      </div>
      <PageController
        v-if="total > 0" :page="page" :page-size="pageSize" :total="total"
        @update:page="handlePageChange"
      />
    </template>
    <template v-else>
      <slot name="fallback">
        <div class="card-area">
          <div class="loading-fallback">
            加载中...
          </div>
        </div>
      </slot>
    </template>
  </LoadingContainer>
</template>

<style scoped>
.no-page-data {
  text-align: center;
  padding: 40px 0;
  color: #888888;
  font-size: 14px;
}

.header {
  color: #6e6e6e;
  font-size: 12px;
  padding: 0px 30px;
}

.card-area {
  padding: 0px 30px;

  .page-status {
    text-align: center;
    padding: 20px 0;
    font-weight: 400;
    font-size: 12px;
    color: #888888;
  }

  .loading-fallback {
    text-align: center;
    padding: 40px 0;
    color: #888888;
    font-size: 14px;
  }
}
</style>
